package cn.qianxun.meta.common.core.utils.url;


import cn.qianxun.meta.common.core.constant.Constants;
import cn.qianxun.meta.common.core.utils.string.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class URLUtil {

    /**
     * 获取网站的端口和IP地址或域名
     *
     * @param uri
     * @return
     */
    public static URI getIP(URI uri) {
        URI effectiveURI = null;
        try {
            // URI(String scheme, String userInfo, String host, int port, String
            // path, String query,String fragment)
            effectiveURI = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
        } catch (Throwable var4) {
            effectiveURI = null;
        }
        return effectiveURI;
    }

    /**
     * 获取网站的端口和IP地址或域名
     *
     * @param uri
     * @return
     */
    public static Map<String, String> getIPInfo(URI uri) {
        Map<String, String> paramMap = new HashMap<>();
        URI effectiveURI = null;
        try {
            // URI(String scheme, String userInfo, String host, int port, String
            // path, String query,String fragment)
            effectiveURI = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
        } catch (Throwable var4) {
            effectiveURI = null;
        }
        String ip = "";
        if (effectiveURI != null) {
            paramMap.put("host", effectiveURI.getHost());
            int port = effectiveURI.getPort();
            String scheme = effectiveURI.getScheme();
            ip = effectiveURI.getHost();
            if (port == -1) {
                if ("https".equals(scheme)) {
                    port = 443;
                } else if ("http".equals(scheme)) {
                    port = 80;
                }
                if (!isIp(ip)) {
                    ip = getMappingIP(ip);
                }
            } else {
                ip = ip.replace(":" + port, "");
                if (!isIp(ip)) {
                    ip = getMappingIP(ip);
                }
            }
            paramMap.put("port", port + "");
        }
        ip = StringUtils.defaultString(ip, "");
        if (StringUtils.isEmpty(ip) || Constants.LOCAL_HOST.equals(ip)) {
            ip = "";
        }
        paramMap.put("effectiveIP", ip);
        return paramMap;
    }

    public static Map<String, String> getIpPortInfo(String urlStr) {
        Map<String, String> paramMap = new HashMap<>();
        if (isIPUrl(urlStr)) {
            //ip
            String ipPattern = "(?i)(?<=://)([^:/]+)";
            Pattern pattern = Pattern.compile(ipPattern);
            Matcher matcher = pattern.matcher(urlStr);
            if (matcher.find()) {
                paramMap.put("ip", matcher.group());
            }
            //port
            String portPattern = "(?<=:)(\\d+)";
            pattern = Pattern.compile(portPattern);
            matcher = pattern.matcher(urlStr);
            if (matcher.find()) {
                int port = Integer.parseInt(matcher.group());
                paramMap.put("port", String.valueOf(port));
            } else {
                if (urlStr.startsWith("https://")) {
                    paramMap.put("port", "443");
                } else if (urlStr.startsWith("http://")) {
                    paramMap.put("port", "80");
                }
            }
        } else {
            try {
                URI uri = URI.create(urlStr);
                URI effectiveURI = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), null, null, null);
                String ip = "";
                if (effectiveURI != null) {
                    paramMap.put("host", effectiveURI.getHost());
                    int port = effectiveURI.getPort();
                    String scheme = effectiveURI.getScheme();
                    ip = effectiveURI.getHost();
                    if (port == -1) {
                        if ("https".equals(scheme)) {
                            port = 443;
                        } else if ("http".equals(scheme)) {
                            port = 80;
                        }
                        if (!isIp(ip)) {
                            ip = getMappingIP(ip);
                        }
                    } else {
                        ip = ip.replace(":" + port, "");
                        if (!isIp(ip)) {
                            ip = getMappingIP(ip);
                        }
                    }
                    paramMap.put("port", port + "");
                }
                ip = StringUtils.defaultString(ip, "");
                if (StringUtils.isEmpty(ip) || Constants.LOCAL_HOST.equals(ip)) {
                    ip = "";
                }
                paramMap.put("ip", ip);

            } catch (Exception e) {
                log.error("获取ip和端口时间超时");
            }
        }
        return paramMap;
    }

    /**
     * 获取端口号
     *
     * @param href 网址, ftp, http, nntp, ... 等等
     * @return
     * @throws IOException
     */
    public static int parsePort(String href) {
        //
        try {
            URL url = new URL(href);
            // 端口号; 如果 href 中没有明确指定则为 -1
            int port = url.getPort();
            if (port < 0) {
                // 获取对应协议的默认端口号
                port = url.getDefaultPort();
            }
            return port;
        } catch (IOException e) {

        }
        return 0;
    }

    /**
     * 获取Host部分
     *
     * @param href 网址, ftp, http, nntp, ... 等等
     * @return
     * @throws IOException
     */
    public static String parseHost(String href) throws IOException {
        //
        URL url = new URL(href);
        // 获取 host 部分
        String host = url.getHost();
        return host;
    }

    /**
     * 根据域名(host)解析IP地址
     *
     * @param host 域名
     * @return
     * @throws IOException
     */
    public static String parseIp(String host) throws IOException {
        // 根据域名查找IP地址
        InetAddress.getAllByName(host);
        InetAddress inetAddress = InetAddress.getByName(host);
        // IP 地址
        String address = inetAddress.getHostAddress();
        return address;
    }

    /**
     * 根据域名获取对应的IP，格式必须为主域名或者子域名格式，不能加https或http
     *
     * @param host
     * @return
     */
    public static String getMappingIP(String host) {
        String ip = "";
        try {
            InetAddress ipadd = InetAddress.getByName(host);
            return ipadd.getHostAddress();
        } catch (Throwable var4) {
            ip = null;
        }
        return ip;
    }

    public static boolean isIp(String ip) {
        try {
            boolean b1 = ip.matches("([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}");
            return b1;
        } catch (Exception e) {
            return false;
        }
    }

    public static String PATTERN_L2DOMAIN = "\\w*\\.\\w*:";
    public static String PATTERN_IP = "(\\d*\\.){3}\\d*";

    public static String getDomain(String host) {
        String url = host;
        if (StringUtils.isEmpty(host)) {
            return "";
        }
        String[] BeReplacedStrs = new String[]{".com.cn", ".edu.cn", ".net.cn", ".org.cn", ".co.jp", ".gov.cn", ".co.uk", ".ac.cn", ".edu", ".tv", ".info", ".com", ".ac", ".ag", ".am", ".at", ".be", ".biz", ".bz", ".cc", ".cn", ".com", ".de", ".es", ".eu", ".fm", ".gs", ".hk", ".in", ".info", ".io", ".it", ".jp", ".la", ".md", ".ms", ".name", ".net", ".nl", ".nu", ".org", ".pl", ".ru", ".sc", ".se", ".sg", ".sh", ".tc", ".tk", ".tv", ".tw", ".us", ".co", ".uk", ".vc", ".vg", ".ws", ".il", ".li", ".ltd", ".me", ".press", ".site", ".top", ".vip", ".work", ".xyz", ".icu", ".club", ".nz"};
        for (String oneBeReplacedStr : BeReplacedStrs) {
            String BeReplacedStr = oneBeReplacedStr + "";
            if (host.indexOf(BeReplacedStr) != -1) {
                host = host.replace(BeReplacedStr, "");
                break;
            }
        }
        int dotIndex = host.lastIndexOf(".");
        host = url.substring(dotIndex + 1);
        return host;
    }

    public static String getDomainNew1(String host) {
        String url = host;
        if (StringUtils.isEmpty(host)) {
            return "";
        }
        String[] BeReplacedStrs = new String[]{".com.cn", ".edu.cn", ".net.cn", ".org.cn", ".co.jp", ".gov.cn", ".co.uk", ".ac.cn", ".edu", ".tv", ".info", ".com", ".ac", ".ag", ".am", ".at", ".be", ".biz", ".bz", ".cc", ".cn", ".com", ".de", ".es", ".eu", ".fm", ".gs", ".hk", ".in", ".info", ".io", ".it", ".jp", ".la", ".md", ".ms", ".name", ".net", ".nl", ".nu", ".org", ".pl", ".ru", ".sc", ".se", ".sg", ".sh", ".tc", ".tk", ".tv", ".tw", ".us", ".co", ".uk", ".vc", ".vg", ".ws", ".il", ".li", ".ltd", ".me", ".press", ".site", ".top", ".vip", ".work", ".xyz", ".icu", ".club", ".nz"};
        for (String oneBeReplacedStr : BeReplacedStrs) {
            String BeReplacedStr = oneBeReplacedStr + "";
            if (host.endsWith(oneBeReplacedStr)) {
                host = host.replace(oneBeReplacedStr, "");
                String[] split = host.split("\\.");
                if (split.length != 0) {
                    host = split[split.length - 1] + oneBeReplacedStr;
                    return host;
                }
            }
        }

        return "";
    }

    public static String getDomainNew(String host) {
        if (StringUtils.isEmpty(host)) {
            return "";
        }
        System.out.println(host.contains("."));
        String[] domainArr = host.split("\\.");
        System.out.println(domainArr.length);
        if (host.endsWith(".com.cn") || host.endsWith(".edu.cn") || host.endsWith(".net.cn") || host.endsWith(".org.cn") || host.endsWith(".co.jp") || host.endsWith(".co.uk") || host.endsWith(".ac.cn")) {
            int length = domainArr.length;
            if (length > 2) {
                host = domainArr[length - 3] + "." + domainArr[length - 2] + "." + domainArr[length - 1];
            } else {
                return host;
            }
        } else {
            int length = domainArr.length;
            if (length > 1) {
                host = domainArr[length - 2] + "." + domainArr[length - 1];
            }
        }
        return host;
    }

    /*** 解析出url请求的ip端口或域名
     * @param url
     * @return
     */
    public static String getUrlPrefix(String url) {
        // 正则表达式规则
        String regEx = "((http|ftp|https)://)(([a-zA-Z0-9._-]+)|([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))(([a-zA-Z]{2,6})?)";
        // 编译正则表达式
        Pattern pattern = Pattern.compile(regEx);
        // 忽略大小写的写法
        Matcher m = pattern.matcher(url);
        // 查找字符串中是否有匹配正则表达式的字符/字符串
        while (m.find()) {
            return m.group();
        }
        return "";
    }

    /**
     * 增加判断是否是IP类网站，是的话为true，不是为false
     *
     * @param url
     * @return
     */
    public static boolean isIPUrl(String url) {
        url = getUrlPrefix(url);
        if (StringUtils.isNotEmpty(url)) {
            url = url.replaceAll("(?:https|ftp|http|:|//)", "");
            if (StringUtils.isNotEmpty(url)) {
                return isIp(url);
            }
            return false;
        }
        return false;
    }

    /**
     * 判断url是否存在多级目录
     *
     * @param url
     * @return
     */
    public static boolean isLevelDirByUrl(String url) {
        if (StringUtils.isNotEmpty(url)) {
            url = url.replaceAll("(?:https|ftp|http|:|//)", "");
            if (StringUtils.isNotEmpty(url)) {
                String[] split = url.trim().split("/");
                if (split.length > 1) {
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }

    /**
     * 判断url是否存在多级目录
     *
     * @param url
     * @return
     */
    public static String getUrlLevelDir(String url) {
        if (StringUtils.isNotEmpty(url)) {
            String[] split1 = url.trim().split("/");
            String preUrlHead = split1[0];
            url = url.replaceAll("(?:https|ftp|http|:|//)", "");
            if (StringUtils.isNotEmpty(url)) {
                String[] split = url.trim().split("/");
                if (split.length > 1) {
                    return preUrlHead + "//" + split[0] + "/" + split[1];
                }
                return null;
            }
            return null;
        }
        return null;
    }

    /**
     * 对比两个url前缀域名或IP是否一样
     *
     * @param parentUrl
     * @param url
     * @return
     */
    public static boolean contrastUrl(String parentUrl, String url) {
        if (StringUtils.isNotEmpty(parentUrl) && StringUtils.isNotEmpty(url)) {
            parentUrl = getDomainOrIP(parentUrl);
            url = getDomainOrIP(url);
            if (StringUtils.isNotEmpty(parentUrl) && StringUtils.isNotEmpty(url)) {
                //去掉https，http,ftp进行判断
                parentUrl = parentUrl.replace("https://", "").replace("http://", "").replace("ftp://", "");
                url = url.replace("https://", "").replace("http://", "").replace("ftp://", "");
                if (parentUrl.equals(url) || (parentUrl + ":80").equals(url) || (parentUrl + ":443").equals(url)) {
                    return true;
                }
                parentUrl = parentUrl.replace(":80", "");
                if (parentUrl.equals(url)) {
                    return true;
                }
                parentUrl = parentUrl.replace(":443", "");
                if (parentUrl.equals(url)) {
                    return true;
                }
                url = url.replace(":80", "");
                if (parentUrl.equals(url)) {
                    return true;
                }
                url = url.replace(":443", "");
                if (parentUrl.equals(url)) {
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }

    /**
     * 获取域名或IP端口
     *
     * @param url
     * @return
     */
    public static String getDomainOrIP(String url) {
        //使用正则表达式过滤，
        String re = "((http|ftp|https)://)(([a-zA-Z0-9._-]+)|([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}))(([a-zA-Z]{2,6})|(:[0-9]{1,4})?)";
        String str = "";
        // 编译正则表达式
        Pattern pattern = Pattern.compile(re);
        // 忽略大小写的写法
        // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(url);
        //若url==http://127.0.0.1:9040或www.baidu.com的，正则表达式表示匹配
        if (matcher.matches()) {
            str = url;
        } else {
            String[] split2 = url.split(re);
            if (split2.length > 1) {
                String substring = url.substring(0, url.length() - split2[1].length());
                str = substring;
            } else {
                str = split2[0];
            }
        }
        return str;
    }


    private static final Pattern PARAM_PATTERN = Pattern.compile("([^&=]+)(?:=([^&]*))?");

    public static Map<String, String> getUrlParams(String url) {
        Map<String, String> params = new HashMap<>();
        int queryIndex = url.indexOf("?");
        try {
            if (queryIndex >= 0) {
                String query = url.substring(queryIndex + 1);
                Matcher matcher = PARAM_PATTERN.matcher(query);
                while (matcher.find()) {
                    String key = URLDecoder.decode(matcher.group(1), "UTF-8");
                    String value = "";
                    if (matcher.groupCount() > 1 && matcher.group(2) != null) {
                        value = URLDecoder.decode(matcher.group(2), "UTF-8");
                    }
                    params.put(key, value);
                }
            }
        } catch (UnsupportedEncodingException e) {
            log.error("获取URL参数失败：" + e.getMessage());
        }
        return params;
    }


    public static void main(String[] args) throws Exception {
        Map<String, String> ipPortInfo = getIpPortInfo("http://192.168.101.20/login");
        System.out.println(ipPortInfo);
//        InetAddress[] ips=InetAddress.getAllByName("blog.csdn.net");
//        for(InetAddress ip: ips) {
//            System.out.println(ip.toString());
//            System.out.println("Address:" + ip.getHostAddress());
//            System.out.println("Name" + ip.getHostName());
//        }
//        System.out.println(getMappingIP("www.csdn.net"));
//        System.out.println(isIp("123.192.168.5"));
//        URI uri=URI.create("https://www.hxrmwhg.com");
//        System.out.println(getIP(uri).getHost()+":"+getIP(uri).getPort()+":"+getIP(uri).getAuthority()+":"+getIP(uri).getScheme());
//        System.out.println(getIPInfo(uri));
//        System.out.println(isIp("123.192.26.69"));

//        Map<String, String> ipMaps = URLUtil.getIPInfo(URI.create("http://www.ayrc.cc/"));
//        String host = ipMaps.get("host");
//        if (StringUtils.isEmpty(host)) {
//            return;
//        }
//        String effectiveIP = ipMaps.get("effectiveIP");
//        String port = ipMaps.get("port");
//        System.out.println(getDomainNew(host));
//        System.out.println(effectiveIP + "_______" + host);
//        boolean ip = URLUtil.isIp(host);
//        System.out.println(ip);
//        String url = getUrlPrefix("https://blog.csdn.net/?111.7.88.240article/details/111.7.88.240");
//        System.out.println(getUrlPrefix("https://111.7.88.240:8080?111.7.88.240article/details/111.7.88.240"));
//        System.out.println(url.replaceAll("(?:https|ftp|http|:|//)", ""));
        //System.out.println(getDomainOrIP("https://blog.csdn.net/?111.7.88.240article/details/111.7.88.240p;region=410526000000"));
    }

}
